/*  This file is part of the comicconquer project
    Copyright (C) 2010 Reach <reach334@gmail.com>

    ComicConquer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This software is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public 
    License along with this software.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "DisplayControler.h"

extern QDialog* g_mainDialog;

#define PAGE_DISTANCE   15

/**
 * Constructor.
 * 
 * @author reach (5/26/2010)
 * 
 * @param profile: Pointer to CoconProfile. 
 * @param parent: Parent widget.
 */
DisplayControler::DisplayControler(CoconProfile* profile, QObject* parent)
: QObject(parent),
m_profile(profile),
m_content(Cot_Scaled),
m_restoredContent(Cot_Scaled),
m_gridId(0),
m_isPrev(false),
m_isMoveUp(false)
{
    In_Log(__FUNCTION__, COCLASSNAME);


    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Add a page to the queue.
 * 
 * @author reach (5/26/2010)
 * 
 * @param page: The struct for diveided page.
 * @param isPrev: Whther it is turn page forwards. 
 */
void DisplayControler::addPage(DivPage* page, bool isPrev)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (page == NULL)
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return; 
    }

    QMutexLocker locker(&page->mutex);

    if (!page->processed)
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    QRect rcScreen = g_mainDialog->rect();

    DisplayPage displayPage;
    displayPage.page = page;
    DisplayRectVec& rects = displayPage.displayRects;

    //-- Scroll mode.
    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        DisplayRect& displayRect = rects[Cot_Scaled];
        displayRect.rcPic = page->images[Cot_Scaled]->rect();
        displayRect.rcScreen.setWidth(CO_MIN(rcScreen.width(), displayRect.rcPic.width()));
        displayRect.rcScreen.setHeight(displayRect.rcPic.height());
        displayRect.rcScreen.moveCenter(rcScreen.center());

        // Up
        if (isPrev)
        {
            // Move up
            if (m_isMoveUp)
            {
                m_isMoveUp = false;

                if (m_pageList.empty())
                {
                    displayRect.rcScreen.moveBottom(rcScreen.bottom());
                }
                else
                {
                    displayRect.rcScreen.moveBottom(m_pageList.first().displayRects[Cot_Scaled].rcScreen.top() - PAGE_DISTANCE);
                }

                // Request new page to pad the remaining space.
                if (displayRect.rcScreen.top() > 0)
                {
                    if (!page->isFirst())
                    {
                        int iPage = page->iPage;
                        int iDivPage = page->iDivPage;

                        if (--iDivPage < 0)
                        {
                            --iPage;
                            iDivPage = 1;
                        }

                        m_pageList.push_front(displayPage);
                        emit requestPage(iPage, iDivPage, true);
                        return;
                    }
                }

                m_pageList.push_front(displayPage);
            }
            // Scroll up
            else
            {
                GridForScroll& lastGrid = page->gridForScrolls.last();
                displayRect.rcScreen.moveTop(-lastGrid.top);
                int dh = lastGrid.bottom - lastGrid.top + PAGE_DISTANCE;

                // Move all the pages.
                for (int i = 0; i < m_pageList.count(); i++)
                {
                    QRect& rcPageScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;
                    rcPageScreen.translate(0, dh);

                    if (rcPageScreen.top() > rcScreen.bottom())
                    {
                        m_pageList.removeAt(i--);
                    }
                }

                m_pageList.push_front(displayPage);

            }

        }
        // Down
        else
        {
            if (m_pageList.isEmpty())
            {
                displayRect.rcScreen.moveTop(0);
            }
            else
            {
                displayRect.rcScreen.moveTop(m_pageList.last().displayRects[Cot_Scaled].rcScreen.bottom() + PAGE_DISTANCE);
            }

            // Request new page to pad the remaining space.
            if (displayRect.rcScreen.bottom() < rcScreen.bottom())
            {
                if (!page->isLast())
                {
                    int iPage = page->iPage;
                    int iDivPage = page->iDivPage;

                    if (++iDivPage > page->iDivPageCount - 1)
                    {
                        ++iPage;
                        iDivPage = 0;
                    }

                    m_pageList.append(displayPage);
                    emit requestPage(iPage, iDivPage);
                    return;
                }
            }

            m_pageList.append(displayPage);
        } // isPrev

    }
    //-- Non scroll mode.
    else
    {
        for (int i = Cot_Origin; i < Cot_End; i++)
        {
            if (page->images[i] == NULL)
            {
                continue;
            }

            rects[i].rcPic = page->images[i]->rect();
            rects[i].rcDisplay.setWidth(CO_MIN(rcScreen.width(), rects[i].rcPic.width()));
            rects[i].rcDisplay.setHeight(CO_MIN(rcScreen.height(), rects[i].rcPic.height()));
            rects[i].rcScreen = rects[i].rcDisplay;

            if (m_profile->imgProfile.option & Opt_RightToLeft)
            {
                rects[i].rcDisplay.moveTopRight(rects[i].rcPic.topRight());
            }
            else
            {
                rects[i].rcDisplay.moveTopLeft(rects[i].rcPic.topLeft());
            }

            if (isPrev)
            {
                rects[i].rcDisplay.moveBottom(rects[i].rcPic.bottom());
            }

            rects[i].rcScreen.moveCenter(rcScreen.center());
        }

        m_pageList.append(displayPage);

    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Get the first page of the queue.
 * 
 * @author reach (5/26/2010)
 * 
 * @return DivPage*: Pointer to the page.
 */
DivPage* DisplayControler::getPage()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (m_pageList.isEmpty())
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return NULL;
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
    return m_pageList.first().page;
}

/**
 * Paint the images in queue.
 * 
 * @author reach (5/26/2010)
 * 
 * @param painter: The QPainter of main diaog.
 * @param colorTable: The color table used to reset gray scale of images.
 */
void DisplayControler::paint(QPainter& painter, QVector<QRgb>& colorTable)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {
        painter.setFont(QFont("", 30, QFont::Normal));
        painter.drawText(g_mainDialog->rect(), Qt::AlignCenter, QString("Loading..."));

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    //-- Scroll mode.
    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        for (int i = 0; i < m_pageList.count(); i++)
        {
            if (!m_pageList[i].page->processed)
            {
                continue;
            }

            m_pageList[i].page->mutex.lock(); //>> lock

            QImage* image = m_pageList[i].page->images[Cot_Scaled];
            QRect& rcScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;

            if (image != NULL)
            {
                if (!colorTable.empty())
                {
                    image->setColorTable(colorTable);
                }
                painter.drawImage(rcScreen, *image);
                painter.fillRect(rcScreen.left(), rcScreen.top() - 1, rcScreen.width(), 2, Qt::black);
                painter.fillRect(rcScreen.left(), rcScreen.bottom(), rcScreen.width(), 2, Qt::black);
            }

            m_pageList[i].page->mutex.unlock(); //<< unlock
        }

        // Draw the scroll mark.
        if (m_profile->iScrollMark)
        {
            DivPage* lastPage = m_pageList.last().page;
            QRect& rcLastScreen = m_pageList.last().displayRects[Cot_Scaled].rcScreen;
            if (!lastPage->processed)
            {
                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }

            lastPage->mutex.lock(); //>> lock

            GridForScrollVec& grids = lastPage->gridForScrolls;
            QRect rcWindow = g_mainDialog->rect();

            int iLastGrid;
            for (iLastGrid = 0; iLastGrid < grids.count(); iLastGrid++)
            {
                if (grids[iLastGrid].bottom + rcLastScreen.top() > rcWindow.bottom())
                {
                    break;
                }
            }

            if (iLastGrid < grids.count() && grids[iLastGrid].top + rcLastScreen.top() > 0)
            {
                int flagTop;

                if (iLastGrid == 0)
                {
                    flagTop = grids[iLastGrid].top + rcLastScreen.top();
                }
                else
                {
                    flagTop = CO_MAX(grids[iLastGrid - 1].bottom + rcLastScreen.top(),
                                     grids[iLastGrid].top + rcLastScreen.top() + PAGE_DISTANCE);
                }

                QRect rcFlag(rcLastScreen.left(), flagTop, 30, 30);
                painter.setPen(Qt::black);
                painter.setFont(QFont("normal", 20));
                painter.fillRect(rcFlag, Qt::white);
                painter.drawRect(rcFlag);
                painter.drawText(rcFlag, Qt::AlignCenter, QString("翻"));
            }

            lastPage->mutex.unlock(); //>> unlock
        }
    }
    //-- Non scroll mode.
    else
    {
        if (!m_pageList.first().page->processed)
        {
            Out_Log(__FUNCTION__, COCLASSNAME);
            return;
        }

        m_pageList.first().page->mutex.lock(); //>> lock

        QImage* image = m_pageList.first().page->images[m_content];
        DisplayRect& displayRect = m_pageList.first().displayRects[m_content];

        if (image != NULL)
        {
            if ((m_content == Cot_Scaled || m_content == Cot_Origin) && !colorTable.empty())
            {
                image->setColorTable(colorTable);
            }
            painter.drawImage(displayRect.rcScreen, *image, displayRect.rcDisplay);
        }

        m_pageList.first().page->mutex.unlock(); //<< unlock

    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Drag the page.
 * 
 * @author reach (5/26/2010)
 * 
 * @param offset: The offset to drag.
 */
void DisplayControler::drag(const QPoint& offset)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        // Forbid.
    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        rcDisplay.translate(offset);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Correct the display rect to keep it in the image rect.
 * 
 * @author reach (5/26/2010)
 * 
 * @param rcDisplay: Display rect.
 * @param rcPic: Image rect.
 */
void DisplayControler::correctRect(QRect& rcDisplay, QRect& rcPic)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (rcDisplay.left() < rcPic.left())
    {
        rcDisplay.moveLeft(rcPic.left());
    }
    else if (rcDisplay.right() > rcPic.right())
    {
        rcDisplay.moveRight(rcPic.right());
    }

    if (rcDisplay.top() < rcPic.top())
    {
        rcDisplay.moveTop(rcPic.top());
    }
    else if (rcDisplay.bottom() > rcPic.bottom())
    {
        rcDisplay.moveBottom(rcPic.bottom());
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Scroll the page up.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::scrollUp()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        QRect rcWindow = g_mainDialog->rect(); 
        QRect& rcFirstScreen = m_pageList.first().displayRects[Cot_Scaled].rcScreen;
        DivPage* firstPage = m_pageList.first().page;
        GridForScrollVec&  grids = firstPage->gridForScrolls;

        //-- Calculate the delta h.
        // Find the first displayed grid.
        int dh;
        int iSelectGrid;
        for (iSelectGrid = 0; iSelectGrid < grids.count(); iSelectGrid++)
        {
            if (grids[iSelectGrid].top + rcFirstScreen.top() >= 0)
            {
                break;
            }
        }

        // Is not the first grid.
        if (iSelectGrid != 0)
        {
            dh = grids[iSelectGrid - 1].top + rcFirstScreen.top();
        }
        // Is the first grid.
        else
        {
            if (firstPage->isFirst())
            {
                emit prevComic();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
            else
            {
                // Request previous page.
                int iPage = firstPage->iPage;
                int iDivPage = firstPage->iDivPage;

                if (--iDivPage < 0)
                {
                    --iPage;
                    iDivPage = 1;
                }

                emit requestPage(iPage, iDivPage, true);

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        // Move all the pages.
        for (int i = 0; i < m_pageList.count(); i++)
        {
            QRect& rcScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;

            rcScreen.translate(0, -dh);

            if (rcScreen.top() > rcWindow.bottom())
            {
                m_pageList.removeAt(i--);
            }
        }

    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        if (rcDisplay.top() == rcPic.top())
        {
            emit prevPage();

            Out_Log(__FUNCTION__, COCLASSNAME);
            return;
        }

        int dh = rcPic.height()
                 / ((rcPic.height() + rcDisplay.height() - 1) / rcDisplay.height())
                 + 1; // Adding 1 to guarantee rcDisplay.bottom == rcPic.bottom after the last scroll.

        rcDisplay.translate(0, -dh);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Scroll the page down.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::scrollDown()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    //-- Scroll mode.
    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        QRect rcWindow = g_mainDialog->rect();

        QRect& rcLastScreen = m_pageList.last().displayRects[Cot_Scaled].rcScreen;
        DivPage* lastPage = m_pageList.last().page;
        GridForScrollVec&  grids = lastPage->gridForScrolls;

        //-- Calculate the delta h.
        // Find the first grid divided by the bottom of the window.
        int dh; 
        int iSelectGrid;
        for (iSelectGrid = 0; iSelectGrid < grids.count(); iSelectGrid++)
        {
            if (grids[iSelectGrid].bottom + rcLastScreen.top() > rcWindow.bottom())
            {
                break;
            }
        }

        // The grid is exist.
        if (iSelectGrid < grids.count())
        {
            if (grids[iSelectGrid].top + rcLastScreen.top() > 0)
            {
                dh = grids[iSelectGrid].top + rcLastScreen.top();
            }
            else
            {
                int gridH = grids[iSelectGrid].bottom - grids[iSelectGrid].top;
                dh = gridH 
                     / ((gridH + rcWindow.height() - 1) / rcWindow.height())
                     + 1; // Adding 1 to guarantee rcDisplay.bottom == rcPic.bottom after the last scroll.

                dh = CO_MIN(dh, grids[iSelectGrid].bottom + rcLastScreen.top() - rcWindow.bottom());
            }
        }
        // Do not exist, it is the case that the bottom of the.
        // Last page is aligned with that of the window.
        else
        {
            dh = rcLastScreen.bottom() + PAGE_DISTANCE;
        }

        if (lastPage->isLast())
        {
            dh = CO_MIN(dh, rcLastScreen.bottom() - rcWindow.bottom());

            if (dh == 0)
            {
                emit nextComic();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        // Move all the pages.
        for (int i = 0; i < m_pageList.count(); i++)
        {
            QRect& rcScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;

            rcScreen.translate(0, -dh);

            if (rcScreen.bottom() < 0)
            {
                m_pageList.removeAt(i--);
            }
        }

        // Request new page to pad the rest of space.
        if (m_pageList.isEmpty() || rcLastScreen.bottom() < rcWindow.bottom())
        {
            int iPage = lastPage->iPage;
            int iDivPage = lastPage->iDivPage;

            if (++iDivPage > lastPage->iDivPageCount - 1)
            {
                ++iPage;
                iDivPage = 0;
            }

            emit requestPage(iPage, iDivPage);
        }

    }
    //-- Non scroll mode.
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        if (rcDisplay.bottom() == rcPic.bottom())
        {
            emit nextPage();

            Out_Log(__FUNCTION__, COCLASSNAME);
            return;
        }

        int dh = rcPic.height() 
                 / ((rcPic.height() + rcDisplay.height() - 1) / rcDisplay.height())
                 + 1; // Adding 1 to guarantee rcDisplay.bottom == rcPic.bottom after the last scroll.

        rcDisplay.translate(0, dh);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Scroll the page left.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::scrollLeft()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        // Forbit
    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        if (rcDisplay.left() == rcPic.left())
        {
            if (m_profile->imgProfile.option & Opt_RightToLeft)
            {
                emit nextPage();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
            else
            {
                emit prevPage();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        rcDisplay.translate(-rcDisplay.width(), 0);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Scroll the page right.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::scrollRight()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        // Forbit
    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        if (rcDisplay.right() == rcPic.right())
        {
            if (m_profile->imgProfile.option & Opt_RightToLeft)
            {
                emit prevPage();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
            else
            {
                emit nextPage();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        rcDisplay.translate(rcDisplay.width(), 0);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Move the page up.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::moveUp()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    //-- Scroll mode.
    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        QRect rcWindow = g_mainDialog->rect();

        QRect& rcFirstScreen = m_pageList.first().displayRects[Cot_Scaled].rcScreen;
        DivPage* firstPage = m_pageList.first().page;

        int dh = m_profile->iMoveDistance;

        if (firstPage->isFirst())
        {
            dh = CO_MIN(dh, -rcFirstScreen.top());

            if (dh == 0)
            {
                emit prevComic();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        // Move all the pages.
        for (int i = 0; i < m_pageList.count(); i++)
        {
            QRect& rcScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;

            rcScreen.translate(0, dh);

            if (rcScreen.top() > rcWindow.bottom())
            {
                m_pageList.removeAt(i--);
            }
        }

        // Request new page to pad the rest of space.
        if (m_pageList.isEmpty() || rcFirstScreen.top() > 0)
        {
            int iPage = firstPage->iPage;
            int iDivPage = firstPage->iDivPage;

            if (--iDivPage < 0)
            {
                --iPage;
                iDivPage = 1;
            }

            m_isMoveUp = true;
            emit requestPage(iPage, iDivPage, true);
        }

    }
    //-- Non scroll mode.
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        rcDisplay.translate(0, -m_profile->iMoveDistance);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Move the page down.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::moveDown()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {

        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    //-- Scroll mode.
    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        QRect rcWindow = g_mainDialog->rect();

        QRect& rcLastScreen = m_pageList.last().displayRects[Cot_Scaled].rcScreen;
        DivPage* lastPage = m_pageList.last().page;

        int dh = m_profile->iMoveDistance;

        if (lastPage->isLast())
        {
            dh = CO_MIN(dh, rcLastScreen.bottom() - rcWindow.bottom());

            if (dh == 0)
            {
                emit nextComic();

                Out_Log(__FUNCTION__, COCLASSNAME);
                return;
            }
        }

        // Move all the pages.
        for (int i = 0; i < m_pageList.count(); i++)
        {
            QRect& rcScreen = m_pageList[i].displayRects[Cot_Scaled].rcScreen;

            rcScreen.translate(0, -dh);

            if (rcScreen.bottom() < 0)
            {
                m_pageList.removeAt(i--);
            }
        }

        // Request new page to pad the rest of space.
        if (m_pageList.isEmpty() || rcLastScreen.bottom() < rcWindow.bottom())
        {
            int iPage = lastPage->iPage;
            int iDivPage = lastPage->iDivPage;

            if (++iDivPage > lastPage->iDivPageCount - 1)
            {
                ++iPage;
                iDivPage = 0;
            }

            emit requestPage(iPage, iDivPage);
        }

    }
    //-- Non scroll mode.
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        rcDisplay.translate(0, m_profile->iMoveDistance);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Move the page left.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::moveLeft()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        // Forbid
    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        rcDisplay.translate(-m_profile->iMoveDistance, 0);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Move the page right.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::moveRight()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (isEmpty())
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        // Forbid
    }
    else
    {
        QRect& rcDisplay = m_pageList.first().displayRects[m_content].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[m_content].rcPic;

        rcDisplay.translate(m_profile->iMoveDistance, 0);

        correctRect(rcDisplay, rcPic);
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Switch between the original image and the scaled image.
 * 
 * @author reach (5/26/2010)
 * 
 * @param pos: If the toggle operation is generate by stylus, it's the click position, otherwise it isn't used.
 */
void DisplayControler::toggleOrigin(const QPoint& pos)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    if (m_profile->imgProfile.option & Opt_ScrollMode)
    {
        Out_Log(__FUNCTION__, COCLASSNAME);
        return;
    }

    if (m_content == Cot_Scaled)
    {
        m_content = Cot_Origin;
        restoreContent();

        QRect& rcDisplay = m_pageList.first().displayRects[Cot_Origin].rcDisplay;
        QRect& rcPic = m_pageList.first().displayRects[Cot_Origin].rcPic;
        DisplayRect& scaledDispalyRect = m_pageList.first().displayRects[Cot_Scaled];

        float rate = (float)rcPic.width() / scaledDispalyRect.rcPic.width();
        QPoint offset = (pos - scaledDispalyRect.rcScreen.topLeft() + scaledDispalyRect.rcDisplay.topLeft()) * rate;

        if (pos.x() != 0)
        {
            rcDisplay.moveCenter(offset);
        }

        correctRect(rcDisplay, rcPic);

    }
    else if (m_content == Cot_Origin)
    {
        m_content = Cot_Scaled;
        restoreContent();
    }

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Set the current display content.
 * 
 * @author reach (5/26/2010)
 * 
 * @param displayContent: The flag of content.
 */
void DisplayControler::setContent(int displayContent)
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_content = displayContent;

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Get the current display content.
 * 
 * @author reach (5/26/2010)
 * 
 * @return int: The flag of content.
 */
int DisplayControler::getContent()
{
    return m_content;
}

/**
 * Restore the current display cotent.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::restoreContent()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_restoredContent = m_content;

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Recover the display content.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::recoverContent()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_content = m_restoredContent;

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Check if the page list is empty.
 * 
 * @author reach (5/26/2010)
 * 
 * @return bool: 
 */
bool DisplayControler::isEmpty()
{
    return m_pageList.isEmpty();
}

/**
 * Clear the page lists.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::clearPages()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_pageList.clear();

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Remove the first page from the page list.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::removeFirstPage()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_pageList.removeFirst();

    Out_Log(__FUNCTION__, COCLASSNAME);
}

/**
 * Remove the last page from the page list.
 * 
 * @author reach (5/26/2010)
 */
void DisplayControler::removeLastPage()
{
    In_Log(__FUNCTION__, COCLASSNAME);

    m_pageList.removeLast();

    Out_Log(__FUNCTION__, COCLASSNAME);
}
